package routers

import (
	"encoding/json"
	"net/http"

	"gitee.com/kessil/chicory/internal/config"
	"gitee.com/kessil/chicory/internal/middleware"
	"gitee.com/kessil/chicory/internal/models"
	"gitee.com/kessil/chicory/internal/repositories"

	"github.com/go-chi/chi/v5"
	"xorm.io/xorm"
)

type UserRouter struct {
	*GenericCRUDRouter[models.User]
	db   *xorm.Engine
	cfg  *config.Config
	repo *repositories.UserRepository
}

func NewUserRouter(db *xorm.Engine, cfg *config.Config) *UserRouter {
	// 定义允许筛选的字段
	allowedFields := []string{"username", "gender", "enable"}

	// 创建泛型CRUD路由器
	genericRouter := NewGenericCRUDRouter[models.User](db, cfg, "user", allowedFields)

	return &UserRouter{
		GenericCRUDRouter: genericRouter,
		db:                db,
		cfg:               cfg,
		repo:              repositories.NewUserRepository(db),
	}
}

func (ur *UserRouter) Routes() chi.Router {
	r := chi.NewRouter()

	// 使用JWT认证中间件
	r.Use(middleware.JWTAuthMiddleware(ur.cfg))

	// 继承泛型CRUD路由（已经包含分页和查询中间件）
	r.Mount("/", ur.GenericCRUDRouter.Routes())

	// 添加用户特有的路由
	r.With(middleware.PaginationMiddleware(ur.cfg), middleware.QueryMiddleware(ur.allowedFields)).Get("/", ur.page)
	r.Get("/detail", ur.detail)
	r.With(middleware.IDParamMiddleware("id")).Patch("/password/reset/{id}", ur.resetPassword)
	r.With(middleware.IDParamMiddleware("id"), middleware.IDParamMiddleware("roleId")).Post("/{id}/roles/{roleId}", ur.addRole)
	r.With(middleware.IDParamMiddleware("id"), middleware.IDParamMiddleware("roleId")).Delete("/{id}/roles/{roleId}", ur.removeRole)

	return r
}

func (ur *UserRouter) page(w http.ResponseWriter, r *http.Request) {
	pageNo, pageSize := middleware.GetPaginationFromContext(r)

	filters := middleware.GetQueryFiltersFromContext(r)
	res, err := ur.repo.ListUserWithRoles(filters, pageNo, pageSize)
	if err != nil {
		middleware.JSONError(w, http.StatusInternalServerError, "Failed to get users")
		return
	}

	middleware.JSONSuccess(w, res)
}

func (ur *UserRouter) addRole(w http.ResponseWriter, r *http.Request) {
	userId := middleware.GetIDFromContext(r, "id")
	roleId := middleware.GetIDFromContext(r, "roleId")

	if err := ur.repo.AddUserRole(userId, roleId); err != nil {
		middleware.JSONError(w, http.StatusInternalServerError, "Failed to add role")
		return
	}

	middleware.JSONSuccess(w, nil)
}

func (ur *UserRouter) removeRole(w http.ResponseWriter, r *http.Request) {
	userId := middleware.GetIDFromContext(r, "id")
	roleId := middleware.GetIDFromContext(r, "roleId")

	if err := ur.repo.RemoveUserRole(userId, roleId); err != nil {
		middleware.JSONError(w, http.StatusInternalServerError, "Failed to remove role")
		return
	}

	middleware.JSONSuccess(w, nil)
}

func (ur *UserRouter) resetPassword(w http.ResponseWriter, r *http.Request) {
	userId := middleware.GetIDFromContext(r, "id")

	var item models.UserPassword
	if err := json.NewDecoder(r.Body).Decode(&item); err != nil {
		middleware.JSONError(w, http.StatusBadRequest, "Invalid request")
		return
	}

	if err := ur.repo.ResetPassword(userId, item.Password); err != nil {
		middleware.JSONError(w, http.StatusInternalServerError, "Failed to reset password")
		return
	}

	middleware.JSONSuccess(w, nil)
}

func (ur *UserRouter) detail(w http.ResponseWriter, r *http.Request) {
	claims, ok := middleware.GetClaimsFromContext(r, "claims")
	if !ok {
		middleware.JSONError(w, http.StatusNotFound, "claims parse faild")
		return
	}
	user, err := ur.repo.GetUserWithDetail(claims.UserId)
	if err != nil {
		middleware.JSONError(w, http.StatusNotFound, "User not found")
		return
	}

	middleware.JSONSuccess(w, user)
}
